#include "Object.h"
#include "Factory.h"
#include <cmath>

Object::Object(const sf::Texture &texture) : sprite(texture)
{
	Factory::AddObject(this);
}

Object::~Object()
{

}



void Car::Update(float deltaTime)
{
	// move car
	if (W)
	{
		const float maxSpeed = 800.0f;
		const float accel = 250.0f * deltaTime;
		velocity += accel;
		velocity = fmin(maxSpeed, velocity);
	}

	if (A || D)
	{
		const float turnArc = 0.5f;
		const float turnSpeed = velocity * turnArc * deltaTime;  // degrees
		float angle = 0.0f;
		if (A) angle -= turnSpeed;
		if (D) angle += turnSpeed;

		sprite.rotate(angle);
	}

	if (Space)
	{
		const float deadThreshold = 100.0f;
		if (!dead && velocity > deadThreshold && !seatbelt)
		{
			dead = true;
			sprite.setTexture(deadTexture);
			body->DIE(this);
		}

		velocity = velocity * powf(0.02f, deltaTime);
	}

	float rotation = sprite.getRotation() * (3.142f / 180.0f);
	float dx = sin(rotation) * velocity * deltaTime;
	float dy = -cos(rotation) * velocity * deltaTime;

	sprite.move(dx, dy);
}

void Car::Render(sf::RenderWindow &win)
{
	// draw car sprite
	Object::Render(win);

	// draw text
	if (seatbelt)
	{
		seatbeltText.setString("SEATBELT ON");
	}
	else
	{
		seatbeltText.setString("SEATBELT OFF");
	}

	if (dead)
		deadText.setString("DEAD");

	win.draw(seatbeltText);
	win.draw(deadText);
}

bool Car::Alert(sf::Event &e)
{
	
	if ((e.type == sf::Event::KeyPressed || e.type == sf::Event::KeyReleased) && !dead && isDriven)
	{
		if (e.key.code == sf::Keyboard::W)     W     = (e.type == sf::Event::KeyPressed);
		if (e.key.code == sf::Keyboard::A)     A     = (e.type == sf::Event::KeyPressed);
		if (e.key.code == sf::Keyboard::S)     S = (e.type == sf::Event::KeyPressed);
		if (e.key.code == sf::Keyboard::D)     D = (e.type == sf::Event::KeyPressed);
		if (e.key.code == sf::Keyboard::Space) Space = (e.type == sf::Event::KeyPressed);

		if (e.key.code == sf::Keyboard::S && e.type == sf::Event::KeyPressed)
			seatbelt = !seatbelt;
	}

	return false;
}


void Body::Update(float deltaTime)
{
	if (dead)
	{
		float rotation = sprite.getRotation() * (3.142f / 180.0f);
		float dx = sin(rotation) * velocity * deltaTime;
		float dy = -cos(rotation) * velocity * deltaTime;
	
		sprite.move(dx, dy);

		velocity = velocity * powf(0.02f, deltaTime);
	}
}

void Body::Render(sf::RenderWindow &win)
{
	// only draw when dead:
	if (dead)
		Object::Render(win);
}

void Body::DIE(Car *car)
{
	sprite.setPosition(car->sprite.getPosition());
	sprite.setRotation(car->sprite.getRotation());

	velocity = car->velocity * 2.0f;
	dead = true;
}


void PlayerChar::Update(float deltaTime)
{
	float upDown, leftRight;
	upDown =    ((W) ? -1 : 0) + ((S) ? 1 : 0);
	leftRight = ((A) ? -1 : 0) + ((D) ? 1 : 0);

	const float moveSpeed = 50.0f;
	upDown    *= deltaTime * moveSpeed;
	leftRight *= deltaTime * moveSpeed;

	if (!dead)
		sprite.move(leftRight, upDown);
}

void PlayerChar::Render(sf::RenderWindow &win)
{
	if (!car->isDriven) Object::Render(win);
}

bool PlayerChar::Alert(sf::Event &e)
{
	if ((e.type == sf::Event::KeyPressed || e.type == sf::Event::KeyReleased))
	{
		if (e.key.code == sf::Keyboard::W)     W = (e.type == sf::Event::KeyPressed);
		if (e.key.code == sf::Keyboard::A)     A = (e.type == sf::Event::KeyPressed);
		if (e.key.code == sf::Keyboard::S)     S = (e.type == sf::Event::KeyPressed);
		if (e.key.code == sf::Keyboard::D)     D = (e.type == sf::Event::KeyPressed);
	}


	if (e.type == sf::Event::KeyPressed && e.key.code == sf::Keyboard::Return)
	{
		// Enter the car when enter pressed:
		float distance;
		sf::Vector2f distVect = (sprite.getPosition() - car->sprite.getPosition());
		distance = sqrtf(distVect.x * distVect.x + distVect.y * distVect.y);
		if ((distance < 32.0f || car->isDriven) && !car->dead)
		{
			car->isDriven = !car->isDriven;
			sprite.setPosition( car->sprite.getPosition());
			W = A = S = D = false;

			const float deathSpeed = 50.0f;
			if (!car->isDriven && car->velocity > deathSpeed)
			{
				sprite.setTexture( deadTexture );
				dead = true;
				car->dead = true;
			}
		}
		return true;

	}

	return false;
}
